﻿using System;
using System.Collections.Generic;
using System.Linq;
using MongoDB.Driver.Builders;
using eCommMongo.Core.Data;
using eCommMongo.Core.Domain.Customers;
using eCommMongo.Core.Domain.Products;
using eCommMongo.Core.Domain.ShoppingCarts;
using eCommMongo.Service.Customers;
using eCommMongo.Service.Events;
using eCommMongo.Service.Products;
using eCommMongo.Service.Securitys;
using yiCommerce.Service.Events;

namespace eCommMongo.Service.ShoppingCarts
{
    public class ShoppingCartService:IShoppingCartService
    {
        private IPermissionService _permissionService;
        private IProductAttributeParser _productAttributeParser;
        private ICustomerService _customerService;
        private readonly IEventPublisher _eventPublisher;
        private IMongoRepository<ShoppingCartItem> _shoppingCartItemRepository;
        private IProductService _productService;


        public ShoppingCartService(IPermissionService permissionService, IProductAttributeParser productAttributeParser, ICustomerService customerService, IEventPublisher eventPublisher, IMongoRepository<ShoppingCartItem> shoppingCartItemRepository, IProductService productService)
        {
            _permissionService = permissionService;
            _productAttributeParser = productAttributeParser;
            _customerService = customerService;
            _eventPublisher = eventPublisher;
            _shoppingCartItemRepository = shoppingCartItemRepository;
            _productService = productService;
        }

        public void DeleteShoppingCartItem(ShoppingCartItem shoppingCartItem)
        {
            //var c = _shoppingCartItemRepository.GetById(shoppingCartItem.Id);
            _shoppingCartItemRepository.Delete(shoppingCartItem.Id);
        }

        public IList<string> AddToCart(string customerId, ProductVariant productVariant, string selectedAttributes, int quantity)
        {
           

            if (productVariant == null)
                throw new ArgumentNullException("productVariant");

            var warnings = new List<string>();

            
          
            if (quantity <= 0)
            {
                warnings.Add("ShoppingCart.QuantityShouldPositive");
                return warnings;
            }


            //var cart = customer.ShoppingCartItems.ToList();

            var cart = _shoppingCartItemRepository.Table().ToList().Where(c => c.CustomerId == customerId).ToList();

            var shoppingCartItem = FindShoppingCartItemInTheCart(cart, productVariant, selectedAttributes);

            if (shoppingCartItem != null)
            {
                //update existing shopping cart item
                int newQuantity = shoppingCartItem.Quantity + quantity;
                warnings.AddRange(GetShoppingCartItemWarnings( productVariant,
                    selectedAttributes,  newQuantity));

                if (warnings.Count == 0)
                {
                    //shoppingCartItem.AttributesXml = selectedAttributes;
                    //shoppingCartItem.Quantity = newQuantity;
                    //shoppingCartItem.UpdatedOnUtc = DateTime.Now;

                    var update = Update<ShoppingCartItem>.Set(c => c.AttributesXml, selectedAttributes)
                                                         .Set(c => c.Quantity, newQuantity)
                                                         .Set(c => c.UpdatedOnUtc, DateTime.Now);

                   _shoppingCartItemRepository.Update(shoppingCartItem.Id, update);
                    //_customerService.UpdateCustomer(customer);

                    //event notification
                    _eventPublisher.EntityUpdated(shoppingCartItem);
                }
            }
            else
            {
                //new shopping cart item
                warnings.AddRange(GetShoppingCartItemWarnings( productVariant,
                    selectedAttributes, quantity));
                if (warnings.Count == 0)
                {
                    DateTime now = DateTime.Now;
                    shoppingCartItem = new ShoppingCartItem()
                    {
                        ProductVariant=  productVariant,
                        AttributesXml = selectedAttributes,
                        Quantity = quantity,
                        CreatedOnUtc = now,
                        UpdatedOnUtc = now,
                        CustomerId = customerId,
                    };

                    _shoppingCartItemRepository.Insert(shoppingCartItem);
                    //customer.ShoppingCartItems.Add(shoppingCartItem);
                    //_customerService.UpdateCustomer(customer);

                    //event notification
                    _eventPublisher.EntityInserted(shoppingCartItem);
                }
            }
            return warnings;

        }

        public IList<string> GetShoppingCartWarnings(IList<ShoppingCartItem> cart)
        {
            var warnings = new List<string>();
            foreach (var c in cart)
            {
                warnings.AddRange(this.GetShoppingCartItemWarnings(c.ProductVariant, string.Empty,c.Quantity));
                
            }
            return warnings;
        }

        public virtual IList<string> GetShoppingCartItemWarnings( ProductVariant productVariant, string selectedAttributes, 
           int quantity)
        {
            if (productVariant == null)
                throw new ArgumentNullException("productVariant");

            var warnings = new List<string>();

            //standard properties
                warnings.AddRange(GetStandardWarnings(productVariant, selectedAttributes,  quantity));

         


          
            return warnings;
        }

        public IList<ShoppingCartItem> GetShoppingCart(string customerId)
        {
            return _shoppingCartItemRepository.Table().ToList().Where(c => c.CustomerId == customerId).ToList();
        }

        private IEnumerable<string> GetShoppingCartItemAttributeWarnings(ProductVariant productVariant, string selectedAttributes)
        {
            throw new NotImplementedException();
        }

        private IEnumerable<string> GetStandardWarnings( ProductVariant productVariant, string selectedAttributes,  int quantity)
        {
       

            if (productVariant == null)
                throw new ArgumentNullException("productVariant");


            var warnings = new List<string>();

            var productId = productVariant.ProductId;
            var product = _productService.GetProductById(productId);
            
            if (product == null)
            {
                warnings.Add(string.Format("product of product variant id  {0} not exist", productVariant.Id ));
                return warnings;
            }


               //deleted?
            if (product.Deleted || productVariant.Deleted)
            {
                warnings.Add("ShoppingCart Product Deleted");
                return warnings;
            }

            //published?
            if (!product.Published || !productVariant.Published)
            {
                warnings.Add("ShoppingCart Product Unpublished");
            }


            if (productVariant.StockQuantity < quantity)
            {
                int maximumQuantityCanBeAdded = productVariant.StockQuantity;
                if (maximumQuantityCanBeAdded <= 0)
                    warnings.Add(string.Format("product {0} OutOfStock", product.ProductName));
                else
                    warnings.Add("quantity exceeds stock");
            }
             return warnings;
        }

        public IList<string> UpdateShoppingCartItem(Customer customer, int shoppingCartItemId, int newQuantity, bool resetCheckoutData)
        {
            throw new System.NotImplementedException();
        }


        public virtual ShoppingCartItem FindShoppingCartItemInTheCart(IList<ShoppingCartItem> shoppingCart, ProductVariant productVariant, string selectedAttributes = "" )
        {
            if (shoppingCart == null)
                throw new ArgumentNullException("shoppingCart");

            if (productVariant == null)
                throw new ArgumentNullException("productVariant");

            foreach (var sci in shoppingCart)
            {
                if (sci.ProductVariant.Id == productVariant.Id)
                {
                    //attributes
                    bool attributesEqual = _productAttributeParser.AreProductAttributesEqual(sci.AttributesXml, selectedAttributes);

     

                    //found?
                    if (attributesEqual )
                        return sci;
                }
            }

            return null;
        }
    }
}